package cn.dwy2002.binaryhandwritingserver.service.impl;

import cn.dwy2002.binaryhandwritingserver.exception.ProjectNotFoundException;
import cn.dwy2002.binaryhandwritingserver.exception.RelationNotFoundException;
import cn.dwy2002.binaryhandwritingserver.exception.ServiceException;
import cn.dwy2002.binaryhandwritingserver.exception.TagNotFoundException;
import cn.dwy2002.binaryhandwritingserver.mapper.ProjectTagMapper;
import cn.dwy2002.binaryhandwritingserver.mapper.ProjectsMapper;
import cn.dwy2002.binaryhandwritingserver.mapper.TagsMapper;
import cn.dwy2002.binaryhandwritingserver.pojo.po.Project;
import cn.dwy2002.binaryhandwritingserver.pojo.po.Tags;
import cn.dwy2002.binaryhandwritingserver.service.service.ProjectTagService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 杜伟毅
 * @version 1.0
 * @since 2025/05/31
 */
@Service
@RequiredArgsConstructor
public class ProjectTagServiceImpl implements ProjectTagService {
    private final ProjectTagMapper projectTagMapper;
    private final ProjectsMapper projectMapper;
    private final TagsMapper tagMapper;

    /**
     * 添加项目-标签关联
     *
     * @param projectId 项目ID
     * @param tagId     标签ID
     * @throws ProjectNotFoundException 项目不存在时抛出
     * @throws TagNotFoundException     标签不存在时抛出
     */
    @Override
    public void addProjectTag(Long projectId, Long tagId)
            throws ProjectNotFoundException, TagNotFoundException {
        // 1. 检查参数是否有效
        if (projectId == null || tagId == null) {
            throw new IllegalArgumentException("项目ID和标签ID不能为空");
        }

        // 2. 检查项目是否存在（假设有 ProjectService 或 ProjectMapper）
        Project project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ProjectNotFoundException(projectId);
        }

        // 3. 检查标签是否存在（假设有 TagService 或 TagMapper）
        Tags tag = tagMapper.selectById(tagId);
        if (tag == null) {
            throw new TagNotFoundException(tagId);
        }

        // 4. 检查是否已存在关联（可选）
        if (projectTagMapper.selectTagsByProjectId(projectId).contains(tagId)) {
            return; // 已存在关联，直接返回
        }

        // 5. 插入关联关系
        projectTagMapper.insertRelation(projectId, tagId);
    }

    /**
     * 批量添加项目标签关联
     *
     * @param projectId 项目ID
     * @param tagIds    标签ID列表
     * @return 成功添加的数量
     * @throws ProjectNotFoundException 项目不存在时抛出
     * @throws TagNotFoundException     标签不存在时抛出
     */
    @Override
    public int batchAddProjectTags(Long projectId, List<Long> tagIds)
            throws ProjectNotFoundException, TagNotFoundException {
        // 1. 检查参数是否有效
        if (projectId == null || tagIds == null || tagIds.isEmpty()) {
            throw new IllegalArgumentException("项目ID和标签ID列表不能为空");
        }

        // 2. 检查项目是否存在
        Project project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ProjectNotFoundException(projectId);
        }

        // 3. 检查所有标签是否存在
        for (Long tagId : tagIds) {
            Tags tag = tagMapper.selectById(tagId);
            if (tag == null) {
                throw new TagNotFoundException(tagId);
            }
        }

        // 4. 获取已存在的关联标签（避免重复插入）
        List<Long> existingTags = projectTagMapper.selectTagsByProjectId(projectId);
        int addedCount = 0;

        // 5. 批量插入新关联
        for (Long tagId : tagIds) {
            if (!existingTags.contains(tagId)) {
                projectTagMapper.insertRelation(projectId, tagId);
                addedCount++;
            }
        }

        return addedCount;
    }

    /**
     * 移除项目-标签关联
     *
     * @param projectId 项目ID
     * @param tagId     标签ID
     * @throws RelationNotFoundException 关联不存在时抛出
     */
    @Override
    public void removeProjectTag(Long projectId, Long tagId)
            throws RelationNotFoundException {
        // 1. 检查参数是否有效
        if (projectId == null || tagId == null) {
            throw new IllegalArgumentException("项目ID和标签ID不能为空");
        }

        // 2. 检查关联是否存在
        List<Long> projectTags = projectTagMapper.selectTagsByProjectId(projectId);
        if (!projectTags.contains(tagId)) {
            throw new RelationNotFoundException(projectId, tagId);
        }

        // 3. 删除关联
        projectTagMapper.deleteByProjectId(projectId);
    }

    /**
     * 清空项目所有标签关联
     *
     * @param projectId 项目ID
     * @return 删除的记录数
     * @throws ProjectNotFoundException 项目不存在时抛出
     */
    @Override
    public int clearProjectTags(Long projectId)
            throws ProjectNotFoundException {
        // 1. 检查参数是否有效
        if (projectId == null) {
            throw new IllegalArgumentException("项目ID不能为空");
        }

        // 2. 检查项目是否存在
        Project project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ProjectNotFoundException(projectId);
        }

        // 3. 获取当前关联数量
        List<Long> existingTags = projectTagMapper.selectTagsByProjectId(projectId);
        int deletedCount = existingTags.size();

        // 4. 清空所有关联
        projectTagMapper.deleteByProjectId(projectId);

        return deletedCount;
    }

    /**
     * 获取项目关联的标签ID列表
     *
     * @param projectId 项目ID
     * @return 标签ID列表（无关联时返回空列表）
     * @throws ProjectNotFoundException 项目不存在时抛出
     */
    @Override
    public List<Long> getProjectTags(Long projectId)
            throws ProjectNotFoundException {
        // 1. 检查参数是否有效
        if (projectId == null) {
            throw new IllegalArgumentException("项目ID不能为空");
        }

        // 2. 检查项目是否存在
        Project project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ProjectNotFoundException(projectId);
        }

        // 3. 查询关联标签
        return projectTagMapper.selectTagsByProjectId(projectId);
    }

    /**
     * 检查项目是否关联指定标签
     *
     * @param projectId 项目ID
     * @param tagId     标签ID
     * @return 存在返回true，否则false
     * @throws ServiceException 查询失败时抛出
     */
    @Override
    public boolean hasTag(Long projectId, Long tagId) throws ServiceException {

        // 1. 检查参数是否有效
        if (projectId == null || tagId == null) {
            return false;
        }

        // 2. 查询项目关联的标签
        List<Long> projectTags = projectTagMapper.selectTagsByProjectId(projectId);
        return projectTags.contains(tagId);

    }
}
